実際に作ってみる・ver0.01〜0.08 まで
▼ はじめに この項ではこれまで解説した技術を元に、実際にシューティングゲームを1本 作って見ることにします。今月掲載のゲーム『一本槍』はこのような制作過程を 経て作られました。 ▼ ver0.01 とりあえず起動して終了するだけのものを作ってみました。先ほどの eshot.x とほとんど代わりませんが、違うところは「エラーチェックをきちんと行ってい る」という事です。エラーチェックは面倒で後回しにされがちな処理ですが、な るべく早いうちに実装して置かないと公開する事になるので最初のバージョンか ら入れる事にしました。 ここで行っているエラーチェックは、 ・テキスト画面が使用中か ・グラフィック画面が使用中か の2点です。これらは IOCS _TGUSEMD の返り値をチェックしています。 今回はゲームと言うこともあり、エラーが発生したらメッセージを出して終了 する事とします。終了と言っても実は一筋縄ではありません。以下を御覧下さい。 ・正しいエラー処理 if (テキスト画面が使用中){ printf("テキスト画面が使用中です¥n"); } else { if (グラフィック画面が使用中){ printf("グラフィック画面が使用中です¥n"); } else { 画面モードを初期化(); ゲーム本体(); 画面モードを元に戻す(); } } このようにエラーチェックを行うためにネスティングがどんどん深くなっていっ てしまいます。また、エラーが発生した所まで行った処理をキャンセルする必要 があります。上記の例では画面モードの初期化ルーチンの事で、画面使用チェッ クでエラーが起きた場合、画面モードを戻してはいけません(画面モードを設定 していないのですから)。 そこで今回はエラー処理をわかりやすく(美しく)実装するためにどの時点で エラーが発生したかを示すグローバル変数 error_level を導入し、エラーが発 生したらその時点で終了処理ルーチン Tini() を呼んでいます。 ---- error_level = ERROR_TUSEMD; if (テキスト画面が使用中) Tini(); /* 返ってこない */ error_level = ERROR_GUSEMD; if (グラフィック画面が使用中) Tini(); /* 返ってこない */ error_level = ERROR_NON; 画面モードを初期化(); ゲーム本体(); Tini(); ---- void Tini(void){ switch(error_level){ case ERROR_NON: 画面モードを元に戻す(); /* break が無い事に注意 */ case ERROR_GUSEMD: /* break が無い事に注意 */ case ERROR_TUSEMD: exit(-1); /* 終了 */ break; default: break; } } ---- このようにすることによりスマートにエラー処理を行う事ができます。 ● 実行=非対応メニューです ◎ main.c ◎ main.h ◎ makefile 初回なので main.h/makefile も見ておきましょう。なお、makefile ですが、 CD-ROM に収録する都合上、大文字の MAKEFILE になっています。 GNU make は TwentyOne の常駐/非常駐とは無関係に常にメイクファイルの大文字/小文字を 区別するため、そのままコンパイルしようとすると「makefile がない」と怒ら れます。そのため、コンパイルする時は MAKEFILE を makefile とリネームして 下さい(IPPON001.LZH の中には小文字のままで収録してありますので、こちら を展開して使用するのがもっとも簡単でしょう)。 ▼ ver0.02 自機を表示して終了します。 ● 実行(要ジョイスティック)=非対応メニューです ◎ main.c ▼ ver0.03 自機が移動できるようにしてみました。自機関係の処理を player.c に分離し ました。 ● 実行(要ジョイスティック)=非対応メニューです ◎ player.h ◎ player.c ▼ ver0.04 LoadXsp() 関数を新設しました。 ● 実行(要ジョイスティック)=非対応メニューです ◎ main.c ▼ ver0.05 整数16bit+小数16bitの固定小数点を使用するようにしました。固定小数点を 使うに当たり、sin/cos テーブルを持つようにしました。これは起動時に毎回計 算しても良いのですが、それだと起動に時間がかかるので、予め maketbl.x で ファイルに書き出しておくようにしました。作成するファイルは TBL/XYTABLE.DAT です。 ファイルが増えてきたのでスプライト関係のファイルを SP/ 以下へと移動し ました。 ● 実行(要ジョイスティック)=非対応メニューです ◎ maketbl.c ◎ player.c player.c の PlayerMove() で座標の操作に ---- player->ly += xytable[PLAYER_SPEED][192].y; ---- のようなテーブルを使用していることに注目して下さい。 ▼ ver0.06 自機ショットの処理を追加しました。それに伴い自機ショット関係の処理をま とめた shot.h / shot.c を新設しました。リスト構造を使用した、少し難しい (このゲームプログラム中で一番難しい?)部分ですが、もし判らない場合は先 ほどの敵弾処理ルーチンの解説に戻って理解を深めて下さい。 ● 実行(要ジョイスティック)=非対応メニューです ◎ shot.h ◎ shot.c ◎ player.c ShotAlloc() は player.c の PlayerMove() でショットボタンが押された時に 呼び出しています。 ▼ ver0.07 敵キャラの処理を追加しました。まだ当たり判定がないためショットを当てて も、自機が当たっても何も起こりません。また、敵キャラは1種類のみです。 enemy.h / enemy.c を追加しました。 ● 実行(要ジョイスティック)=非対応メニューです ◎ enemy.h ◎ enemy.c ◎ 敵キャラ ◎ 敵キャラの .obj ファイル 敵キャラの処理ルーチン enemy.c は shot.c とほとんど同内容です。自機ショッ トの場合は ShotInit() で初期化し、ShotAlloc() で発生、垂直同期ごとに ShotMove() を実行し、消去する時は ShotFree() を実行していましたが、これ を EnemyInit() / EnemyAlloc() / EnemyMove() / EnemyFree() にしただけです。 この敵キャラは11.25度づつ回転し、32パターンで一周します(回転処理はま だ入っていません)。左右反転可能なので複合スプライトとして登録するのは16 パターンだけです。 ▼ ver0.08 複数の種類の敵キャラを扱えるようにしました。また、敵キャラのアニメーショ ン処理を追加しました。 ● 実行(要ジョイスティック)=非対応メニューです ◎ enemy.c アニメーション処理は enemy.c 内で、 --- p->pt++; /* 複合スプライトのパターン番号を1つづつ増やす */ if (p->pt > obj_zako02 + 15) p->pt = obj_zako02; ---- のように行っています。 (EOF)